﻿
/*
 *
 * Copyright (C) 2008 Mattias Blomqvist, patr-blo at dsv dot su dot se
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

using System;
using System.Collections.Generic;
using FlowLib.Containers;
using ClientExample.Containers;
using ClientExample.Converters;

namespace ClientExample.Controls
{
    public class FriendsControl : ExpandablePanel
    {
        private ListViewFriendslist listViewUserlist1;
        protected Friend tmpFriend = new Friend();
        private System.Windows.Forms.ContextMenuStrip friendMenuStrip;
        private System.ComponentModel.IContainer components;
        private System.Windows.Forms.ToolStripMenuItem sendMessageToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem renameToolStripMenuItem;
        private System.Windows.Forms.ToolStripMenuItem removeToolStripMenuItem;
        protected SortedList<string, HubControl> hubs = new SortedList<string, HubControl>();
        protected int selectedIndex = 0;

        protected delegate void voidFuncDelegate();

        public FriendsControl()
        {
            InitializeComponent();
            label1.Text = "Friends";
            Expanded = false;
            listViewUserlist1.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(listViewUserlist1_ItemSelectionChanged);

            Program.Settings.SavedFriends.ItemAdded += new FlowSortedList<Friend>.SingleChangedDelegate(SavedFriends_ItemAdded);
            Program.Settings.SavedFriends.ItemRemoved += new FlowSortedList<Friend>.SingleChangedDelegate(SavedFriends_ItemRemoved);

            System.Collections.Generic.List<Containers.Friend> tmpFriends = new System.Collections.Generic.List<ClientExample.Containers.Friend>(Program.Settings.SavedFriends);
            for (int i = 0; i < tmpFriends.Count; i++)
            {
                listViewUserlist1.AllItems.Add(tmpFriends[i]);
            }
        }

        void listViewUserlist1_ItemSelectionChanged(object sender, System.Windows.Forms.ListViewItemSelectionChangedEventArgs e)
        {
            if (e.IsSelected)
            {
                selectedIndex = e.ItemIndex;
            }
        }

        void SavedFriends_ItemRemoved(int pos, Friend item)
        {
            listViewUserlist1.AllItems.Remove(item);
        }

        void SavedFriends_ItemAdded(int pos, Friend item)
        {
            listViewUserlist1.AllItems.Add(item);
        }

        public void AddHub(HubControl hub)
        {
            try
            {
                hub.HubUpdate += new FlowLib.Events.FmdcEventHandler(OnHubUpdate);
                hubs.Add(EncodeString(hub.Id), hub);
            }
            catch (ArgumentException)
            {

            }
        }

        protected string EncodeString(string key)
        {
            FlowLib.Utils.Hash.Tiger tiger = new FlowLib.Utils.Hash.Tiger();
            tiger.Initialize();
            key = FlowLib.Utils.Convert.Base32.Encode(tiger.ComputeHash(System.Text.Encoding.UTF8.GetBytes(key)));
            tiger.Clear();
            return key;
        }

        public void OnHubUpdate(object sender, FlowLib.Events.FmdcEventArgs e)
        {
            ClientExample.Controls.HubControl hub = sender as ClientExample.Controls.HubControl;
            if (hub == null)
                return;
            switch (e.Action)
            {
                case EventActions.OnlineStatusChange:
                    OnlineStatus status = e.Data as OnlineStatus;
                    if (status != null)
                    {
                        try
                        {
                            if (status.UserId != null)
                            {
                                // User online status has been changed
                                int pos = 0;
                                bool shouldUpdate = false;
                                tmpFriend.Set(UserInfo.STOREID, status.UserStoreID);
                                if ((pos = Program.Settings.SavedFriends.Find(tmpFriend)) != -1)
                                {
                                    // User exist as friend.
                                    Friend friend = Program.Settings.SavedFriends[pos];
                                    string hubid = EncodeString(hub.Id);
                                    if (status.Status == FlowLib.Connections.TcpConnection.Connected)
                                    {
                                        try
                                        {
                                            // Update information
                                            User usr = hub.Users[status.UserId];
                                            UpdateFriendFromUserInfo(friend, usr.UserInfo);
                                            friend.Set(hubid, status.UserId);
                                            friend.Set("HUBS", hubid + "." + friend.Get("HUBS"));
                                            friend.OnlineStatus = status.Status;
                                            shouldUpdate = true;
                                        }
                                        catch { }
                                    }
                                    else
                                    {
                                        friend.Remove(hubid);
                                        string str = friend.Get("HUBS").Replace(hubid + ".", "");
                                        friend.Set("HUBS", str);
                                        // Do we have more hubs as source for this user?
                                        if (string.IsNullOrEmpty(str))
                                        {
                                            friend.OnlineStatus = status.Status;
                                            friend.LastSeen = DateTime.Now.Ticks;
                                            shouldUpdate = true;
                                        }
                                    }
                                    if (shouldUpdate)
                                    {
                                        this.Invoke(new voidFuncDelegate(OnRedrawList));
                                    }
                                }
                            }
                            else if (status.Status != FlowLib.Connections.TcpConnection.Connected)
                            {
                                // Hub online status has been changed
                                bool needRefresh = false;
                                FlowSortedList<Friend> tmpFriends = new FlowSortedList<Friend>(Program.Settings.SavedFriends, Program.Settings.SavedFriends.Comparer);
                                string hubid = EncodeString(hub.Id);
                                foreach (Friend friend in tmpFriends)
                                {
                                    if (friend.ContainsKey(hubid))
                                    {
                                        // Hub has been disconnected. Remove this hub as source for user.
                                        friend.Remove(hubid);
                                        string tmp = friend.Get("HUBS").Replace(hubid + ".", "");
                                        friend.Set("HUBS", tmp);
                                        // Do we have user in more hubs?
                                        if (string.IsNullOrEmpty(tmp))
                                        {
                                            friend.OnlineStatus = status.Status;
                                            friend.LastSeen = DateTime.Now.Ticks;
                                            needRefresh = true;
                                        }
                                    }
                                }
                                tmpFriends = null;
                                if (needRefresh)
                                    this.Invoke(new voidFuncDelegate(OnRedrawList));
                            }
                        }
                        catch { }
                    }
                    break;
                case EventActions.UserInfoChanged:
                    UserInfo usrInfo = e.Data as UserInfo;
                    if (usrInfo != null)
                    {
                        int pos = 0;
                        tmpFriend.Set(UserInfo.STOREID, usrInfo.StoreID);
                        if ((pos = Program.Settings.SavedFriends.Find(tmpFriend)) != -1)
                        {
                            Friend friend = Program.Settings.SavedFriends[pos];
                            UpdateFriendFromUserInfo(friend, usrInfo);
                        }
                        this.Invoke(new voidFuncDelegate(OnRedrawList));
                    }
                    break;
            }
        }

        protected void UpdateFriendFromUserInfo(Friend friend, UserInfo userinfo)
        {
            friend.Share = userinfo.Share;
        }

        protected void OnRedrawList()
        {
            listViewUserlist1.Invalidate(true);
        }

        private void sendMessageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (listViewUserlist1.Items.Count > selectedIndex)
            {
                Friend friend = listViewUserlist1.Items[selectedIndex];
                HubControl hub = null;
                string hubid = null;
                foreach (KeyValuePair<string, HubControl> hubPair in hubs)
                {
                    if (friend.ContainsKey(hubPair.Key))
                    {
                        hub = hubPair.Value;
                        hubid = hubPair.Key;
                        break;
                    }
                }

                if (hub != null && hubid != null)
                {
                    string userid = friend.Get(hubid);
                    Message msg = new Message();
                    msg.To = userid;
                    msg.IsSystem = true;
                    msg.GroupId = hub.Id + userid;
                    msg.GroupName = friend.DisplayName;
                    msg.Content = "Do not write sensitive information like pay card nr and more here. It can be gathered by others.";
                    msg.Status = new OnlineStatus(hub.Id, userid, friend.StoreID, FlowLib.Connections.TcpConnection.Connected);
                    hub.FireHubUpdate(new FlowLib.Events.FmdcEventArgs(EventActions.ForceOpenMessage, msg));
                }
            }
        }

        private void removeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (listViewUserlist1.Items.Count > selectedIndex)
            {
                Friend friend = listViewUserlist1.Items[selectedIndex];
                Program.Settings.SavedFriends.Remove(friend);
            }
        }

        private void renameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (listViewUserlist1.Items.Count > selectedIndex)
            {
                Friend friend = listViewUserlist1.Items[selectedIndex];
                Client.Interface.QuestionWindow qw = new ClientExample.Client.Interface.QuestionWindow();
                qw.txtAnswer.Text = friend.DisplayName;
                if (qw.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    friend.DisplayName = qw.txtAnswer.Text;
                    this.Invoke(new voidFuncDelegate(OnRedrawList));
                    Program.Save();
                }
            }
        }

        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            ClientExample.Converters.FriendConverter friendConverter1 = new ClientExample.Converters.FriendConverter();
            ClientExample.Filters.FriendsFilter friendsFilter1 = new ClientExample.Filters.FriendsFilter();
            this.listViewUserlist1 = new ClientExample.Controls.ListViewFriendslist();
            this.friendMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
            this.sendMessageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.renameToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.removeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
            this.splitContainer1.Panel1.SuspendLayout();
            this.splitContainer1.Panel2.SuspendLayout();
            this.splitContainer1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
            this.friendMenuStrip.SuspendLayout();
            this.SuspendLayout();
            // 
            // splitContainer1
            // 
            // 
            // splitContainer1.Panel2
            // 
            this.splitContainer1.Panel2.Controls.Add(this.listViewUserlist1);
            this.splitContainer1.Size = new System.Drawing.Size(198, 269);
            // 
            // label1
            // 
            this.label1.Size = new System.Drawing.Size(82, 22);
            // 
            // listViewUserlist1
            // 
            this.listViewUserlist1.Comparer = null;
            this.listViewUserlist1.ContextMenuStrip = this.friendMenuStrip;
            this.listViewUserlist1.Converter = friendConverter1;
            this.listViewUserlist1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.listViewUserlist1.Filter = friendsFilter1;
            this.listViewUserlist1.FullRowSelect = true;
            this.listViewUserlist1.LabelWrap = false;
            this.listViewUserlist1.Location = new System.Drawing.Point(0, 0);
            this.listViewUserlist1.Name = "listViewUserlist1";
            this.listViewUserlist1.ShowGroups = false;
            this.listViewUserlist1.Size = new System.Drawing.Size(198, 246);
            this.listViewUserlist1.TabIndex = 0;
            this.listViewUserlist1.UseCompatibleStateImageBehavior = false;
            this.listViewUserlist1.View = System.Windows.Forms.View.Details;
            this.listViewUserlist1.VirtualMode = true;
            // 
            // friendMenuStrip
            // 
            this.friendMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.sendMessageToolStripMenuItem,
            this.renameToolStripMenuItem,
            this.removeToolStripMenuItem});
            this.friendMenuStrip.Name = "friendMenuStrip";
            this.friendMenuStrip.Size = new System.Drawing.Size(153, 92);
            // 
            // sendMessageToolStripMenuItem
            // 
            this.sendMessageToolStripMenuItem.Name = "sendMessageToolStripMenuItem";
            this.sendMessageToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.sendMessageToolStripMenuItem.Text = "Send Message";
            this.sendMessageToolStripMenuItem.Click += new System.EventHandler(this.sendMessageToolStripMenuItem_Click);
            // 
            // renameToolStripMenuItem
            // 
            this.renameToolStripMenuItem.Name = "renameToolStripMenuItem";
            this.renameToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.renameToolStripMenuItem.Text = "Rename";
            this.renameToolStripMenuItem.Click += new System.EventHandler(this.renameToolStripMenuItem_Click);
            // 
            // removeToolStripMenuItem
            // 
            this.removeToolStripMenuItem.Name = "removeToolStripMenuItem";
            this.removeToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
            this.removeToolStripMenuItem.Text = "Remove";
            this.removeToolStripMenuItem.Click += new System.EventHandler(this.removeToolStripMenuItem_Click);
            // 
            // FriendsControl
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.Name = "FriendsControl";
            this.Size = new System.Drawing.Size(198, 269);
            this.Controls.SetChildIndex(this.splitContainer1, 0);
            this.splitContainer1.Panel1.ResumeLayout(false);
            this.splitContainer1.Panel2.ResumeLayout(false);
            this.splitContainer1.ResumeLayout(false);
            ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
            this.friendMenuStrip.ResumeLayout(false);
            this.ResumeLayout(false);

        }
    }
}
